package com.geekgo.lucenepp.core.config.datasource;

import com.geekgo.lucenepp.model.Field;
import com.geekgo.lucenepp.util.XMLUtil;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.ControlledRealTimeReopenThread;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ReferenceManager;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.FSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wltea.analyzer.lucene.IKAnalyzer;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

/**
 * lucene数据源
 *
 * @author HeHaoyang
 * @create 2017-06-13 17:01
 **/
public class LuceneDataSource {

    private final Logger logger = LoggerFactory.getLogger(LuceneDataSource.class);
    //分词器选择
    private Analyzer analyzer = new IKAnalyzer(false);

    private IndexWriter indexWriter;

    private IndexReader indexReader;

    //高亮
    private Boolean highlight;
    private String[]  highlightConfig = new String[]{"<font color='red'>","</font>"};

    //数据源 名称
    private String core;

    //索引根目录
    private String  luceneBasePath;

    //非法字符
    private String illegalFiltering;

    //索引目录
    private FSDirectory fsDirectory;

    //查询
    private List<Map<String,String>> isQuery;

    //全部字段
    private List<Field> xmlDem;
    //查询字段数量
    private static int queryFieldNum = 0;

    private SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(highlightConfig[0],highlightConfig[1]);

    private ReferenceManager<IndexSearcher> reMgr;//类似于Lucene3.x中的NrtManager
    private ControlledRealTimeReopenThread<IndexSearcher> crt;

    @PostConstruct
    public void  init(){
        logger.info("Lucene数据源:"+this.core+"->开始初始化...");
        String luceneCore = this.luceneBasePath+this.core;
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(this.analyzer);
        try {
            this.fsDirectory = FSDirectory.open(Paths.get(luceneCore + "/data"));
            this.indexWriter = new IndexWriter(fsDirectory,indexWriterConfig);
            //IndexReader,基于IndexWriter打开的IndexReader
            this.indexReader = DirectoryReader.open(indexWriter,true,true);
        } catch (IOException e) {
            logger.error("lucene数据源加载失败！"+e);
        }
        this.highlight = false;
        this.xmlDem = XMLUtil.xmlTOObj(luceneCore + "/conf/config.xml");
        this.simpleHTMLFormatter = new SimpleHTMLFormatter(this.highlightConfig[0],this.highlightConfig[1]);
        logger.info("Lucene数据源:"+this.core+"->初始化完毕...");
    }

    @PreDestroy
    public void  dostory(){
        logger.info("Lucene数据源:"+this.core+"->开始销毁...");
        if(this.indexWriter != null) {
            try {
                indexWriter.close();
            } catch (IOException e) {
                logger.error("lucene indexWriter 关闭异常！",e);
            }
        }
        if(this.indexReader != null) {
            try {
                indexReader.close();
            } catch (IOException e) {
                logger.error("lucene indexReader 关闭异常！",e);
            }
        }
        logger.info("Lucene数据源:"+this.core+"->销毁完毕...");
    }

    public Analyzer getAnalyzer() {
        return analyzer;
    }

    public void setAnalyzer(Analyzer analyzer) {
        this.analyzer = analyzer;
    }

    public IndexWriter getIndexWriter() {
        return indexWriter;
    }

    public void setIndexWriter(IndexWriter indexWriter) {
        this.indexWriter = indexWriter;
    }

    public IndexReader getIndexReader() {
        try {
            //openIfChanged,如果有提交或未提交的变化，就打开新的indexreader。记住关闭old reader
            IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader)this.indexReader,this.indexWriter,true);
            if(newReader != null){
                this.indexReader.close();
                this.indexReader = newReader;
            }
        } catch (IOException e) {
            logger.error("lucene IndexReader 获取异常！",e);
        }
        return indexReader;
    }

    public void setIndexReader(IndexReader indexReader) {
        this.indexReader = indexReader;
    }

    public Boolean getHighlight() {
        return highlight;
    }

    public void setHighlight(Boolean highlight) {
        this.highlight = highlight;
    }

    public String[] getHighlightConfig() {
        return highlightConfig;
    }

    public void setHighlightConfig(String[] highlightConfig) {
        this.highlightConfig = highlightConfig;
    }

    public String getCore() {
        return core;
    }

    public void setCore(String core) {
        this.core = core;
    }

    public String getLuceneBasePath() {
        return luceneBasePath;
    }

    public void setLuceneBasePath(String luceneBasePath) {
        this.luceneBasePath = luceneBasePath;
    }

    public String getIllegalFiltering() {
        return illegalFiltering;
    }

    public void setIllegalFiltering(String illegalFiltering) {
        this.illegalFiltering = illegalFiltering;
    }

    public FSDirectory getFsDirectory() {
        return fsDirectory;
    }

    public void setFsDirectory(FSDirectory fsDirectory) {
        this.fsDirectory = fsDirectory;
    }

    public List<Map<String, String>> getIsQuery() {
        return isQuery;
    }

    public void setIsQuery(List<Map<String, String>> isQuery) {
        this.isQuery = isQuery;
    }

    public List<Field> getXmlDem() {
        return xmlDem;
    }

    public void setXmlDem(List<Field> xmlDem) {
        this.xmlDem = xmlDem;
    }

    public static int getQueryFieldNum() {
        return queryFieldNum;
    }

    public static void setQueryFieldNum(int queryFieldNum) {
        LuceneDataSource.queryFieldNum = queryFieldNum;
    }

    public SimpleHTMLFormatter getSimpleHTMLFormatter() {
        return simpleHTMLFormatter;
    }

    public void setSimpleHTMLFormatter(SimpleHTMLFormatter simpleHTMLFormatter) {
        this.simpleHTMLFormatter = simpleHTMLFormatter;
    }

    public ReferenceManager<IndexSearcher> getReMgr() {
        return reMgr;
    }

    public void setReMgr(ReferenceManager<IndexSearcher> reMgr) {
        this.reMgr = reMgr;
    }

    public ControlledRealTimeReopenThread<IndexSearcher> getCrt() {
        return crt;
    }

    public void setCrt(ControlledRealTimeReopenThread<IndexSearcher> crt) {
        this.crt = crt;
    }
}
